home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
PC World Komputer 2010 April
/
PCWorld0410.iso
/
pluginy Firefox
/
138
/
138.xpi
/
chrome
/
stumbleupon.jar
/
content
/
prefetcher.js
< prev
next >
Wrap
Text File
|
2009-08-03
|
13KB
|
509 lines
function su_Prefetcher()
{
//!!! We need to get the mouse cursor load clock image to not spin.
// background:
// The cursor is set by the docshell's progress listener implementation.
// http://lxr.mozilla.org/seamonkey/source/docshell/base/nsDocShell.cpp#4778
// http://lxr.mozilla.org/aviary101branch/source/docshell/base/nsDocShell.cpp#4537
//### private attributes
var service;
try {
service = Components.classes["@stumbleupon.com/stumbleupon-service;1"].getService().wrappedJSObject;
}
catch (e) {
// seamonkey kludge
service = su_service;
}
this.ds = service.getDatastore();
this.URIsIndex = -1;
this.URIs = new Array();
this.referrersByURI = new Object();
this.redirectTargetsByURI = new Object();
this.passCountsByURI = new Object();
this.statesByURI = new Object();
this.urlDetailByURI = new Object();
this.httpStatusesByURI = new Object();
this.target = null;
this.id = su_Prefetcher.instanceCount++;
this.browserId = "su_prefetcher" + this.id;
this.passCount = 1;
this.URIsTopIndex = 0;
this.URIsBottomIndex = -1;
this.eventListenerListsByEventId = new Object();
this.queueLocked = false;
//### public attributes
this.mode = "complete";
this.pass1TimeoutInterval = 10000;
this.pass2TimeoutInterval = 30000;
this.pass3TimeoutInterval = 120000;
this.passMax = 3;
this.disabled = false;
this.delayedStartInterval = 0;
this.pauseForScriptRedirectInterval = 800;
this.continuous = true;
this.maintainHistory = false;
this.allTargetsPrefetched = true;
this.fetchAheadDepth = -1;
//### private methods
this._start = function()
{
if (this.disabled)
return;
if (this.allTargetsPrefetched)
return;
var browser = document.getElementById(this.browserId);
if (browser)
{
this._logRedirectTarget();
document.getElementById("main-window").removeChild(browser);
}
var found = false;
var uri;
while ((! found) && ((this.URIsIndex + 1) <= this.URIsBottomIndex))
{
this.URIsIndex++;
uri = this.URIs[this.URIsIndex];
if ((this.statesByURI[uri] == "new") ||
((this.passCount > 1) && (this.passCountsByURI[uri] > 1) &&
(this.passCountsByURI[uri] < this.passMax) &&
(this.statesByURI[uri] == "timed-out")))
{
found = true;
}
}
if (! found)
{
this.passCount++;
if (this.passCount > this.passMax)
{
this.target = null;
this.allTargetsPrefetched = true;
this._dispatchEvent("done");
if (this.ds.getValue("@log_prefetch_progress"))
su_log("prefetching done");
}
else if (! this.allTargetsPrefetched)
{
this.target = null;
this.URIsIndex = this.URIsTopIndex - 1;
this._start();
}
return;
}
this.target = uri;
// The technique of deleting/creating a browser each time and
// applying to it the style attribute below is derived from the
// Cooliris extension with permission from its developers. -- JW
browser = document.createElement("browser");
browser.setAttribute("id", this.browserId);
browser.setAttribute("type", "content");
browser.setAttribute("src", "about:blank");
browser.setAttribute("style", "visibility:hidden;overflow:auto;border:0px solid black;background-color:white;width:0px;height:0px;");
document.getElementById("main-window").appendChild(browser);
browser.docShell.allowJavascript = true;
browser.docShell.allowMetaRedirects = true;
browser.docShell.allowAuth = false;
browser.docShell.allowPlugins = false;
browser.docShell.allowSubframes = true;
if (this.mode == "DOM")
{
browser.addEventListener("DOMContentLoaded", function () { this.handleDocumentLoad("DOMContentLoaded"); }, true);
}
browser.addProgressListener(this);
try {
browser.loadURI(this.target, su_get_nsiuri(this.referrersByURI[this.target]), null);
} catch (e) {
su_log_error("prefetch load error", e, this.target);
}
// if (browser.contentDocument.contentType != "text/html")
// {
// browser.stop();
// this.URIsIndex++;
// this._start();
// }
var interval;
switch (this.passCountsByURI[this.target])
{
case 1: interval = this.pass1TimeoutInterval; break;
case 2: interval = this.pass2TimeoutInterval; break;
case 3: interval = this.pass3TimeoutInterval; break;
}
if (this.ds.getValue("@log_prefetch_progress"))
su_log("prefetching " + (this.URIsIndex + 1) + " of " + this.URIs.length, this.target, "pass " + this.passCount + " with timeout " + interval + "ms");
this.timer = setTimeout(function (prefetcher) { prefetcher._finishPrefetch("timeout"); }, interval, this)
}
this._finishPrefetch = function (from)
{
if (this.ds.getValue("@log_prefetch_progress"))
su_log("finish", from);
var state;
switch (from)
{
case "timeout": state = "timed-out"; break;
case "pause":
case "stop":
case "advance": state = "new"; break;
case "skip": state = "skipped"; break;
case "load": state = "fetched"; break;
}
this.statesByURI[this.target] = state;
if (this.timer)
{
clearTimeout(this.timer);
}
if (this.pauseForScriptRedirectTimer)
{
clearTimeout(this.pauseForScriptRedirectTimer);
}
if ((from == "load") || (from == "timeout"))
this.passCountsByURI[this.target]++;
if (from == "stop")
{
var browser = document.getElementById(this.browserId);
if (browser)
{
document.getElementById("main-window").removeChild(browser);
}
}
if ((from == "pause") && (from == "stop"))
return;
if (this.continuous)
{
setTimeout(function (prefetcher) { prefetcher._start(); }, this.pauseForScriptRedirectInterval, this);
}
else
{
this._logRedirectTarget();
this.pauseForScriptRedirectTimer = setTimeout(function (prefetcher) { prefetcher._logRedirectTarget; }, this.pauseForScriptRedirectInterval, this);
}
}
this._logRedirectTarget = function ()
{
if (! this.target)
return;
if (this.ds.getValue("@log_prefetch_progress"))
su_log("logging " + (this.URIsIndex + 1) + " of " + this.URIs.length, this.target, "pass " + this.passCount, "state " + this.statesByURI[this.target]);
var browser = document.getElementById(this.browserId);
if (browser && browser.contentDocument && browser.contentDocument.location)
{
this.redirectTargetsByURI[this.target] = browser.contentDocument.location.href;
}
}
this._updateBottomIndex = function ()
{
if (this.fetchAheadDepth == -1)
{
this.URIsBottomIndex = this.URIs.length - 1;
}
else
{
this.URIsBottomIndex = this.URIsTopIndex + this.fetchAheadDepth - 1;
if (this.URIsBottomIndex > this.URIs.length - 1)
{
this.URIsBottomIndex = this.URIs.length - 1;
}
}
}
this._dispatchEvent = function (eventId)
{
var listeners = this.eventListenerListsByEventId[eventId];
if (! listeners)
return;
var i;
for (i = 0; i < listeners.length; i++)
{
var event = new Object();
event.target = this;
listeners[i](event);
}
}
//### privileged methods
this.handleDocumentLoad = function (from)
{
var browser = document.getElementById(this.browserId);
if ((((from == "DOMContentLoaded") && (this.mode == "DOM")) ||
((from == "progress-stop") && (this.mode == "complete"))) &&
browser && browser.contentDocument &&
browser.contentDocument.location &&
(browser.contentDocument.location.href != "about:blank"))
{
this._finishPrefetch("load");
}
}
this.setQueueLock = function (state)
{
this.queueLocked = state;
}
this.addTarget = function (urlDetail)
{
if (this.queueLocked)
return;
if (! this.statesByURI[urlDetail.url])
{
this.urlDetailByURI[urlDetail.url] = urlDetail;
this.statesByURI[urlDetail.url] = "new";
this.allTargetsPrefetched = false;
this.URIs.push(urlDetail.url);
this.passCount = 1;
this.passCountsByURI[urlDetail.url] = 1;
this._updateBottomIndex();
this.referrersByURI[urlDetail.url] = urlDetail.referrer;
}
}
this.skipCurrentTarget = function ()
{
this._finishPrefetch("skip");
}
this.advancePastTarget = function (uri)
{
var i;
this._finishPrefetch("advance");
for (i = 0; i < this.URIs.length; i++)
{
if (this.URIs[i] == uri)
{
if (i >= this.URIsBottomIndex)
{
this.allTargetsPrefetched = true;
break;
}
else
{
this.passCount = 1;
this.allTargetsPrefetched = false;
this.URIsTopIndex = i + 1;
if (this.URIsIndex < this.URIsTopIndex)
{
this.URIsIndex = this.URIsTopIndex;
}
this._updateBottomIndex();
}
}
}
}
this.clearTargets = function ()
{
this.URIsIndex = -1;
this.allTargetsPrefetched = true;
this.URIs = new Array();
if (! this.maintainHistory)
{
this.clearHistory();
}
}
this.clearHistory = function ()
{
this.passCountsByURI = new Object();
this.redirectTargetsByURI = new Object();
this.statesByURI = new Object();
this.referrersByURI = new Object();
this.httpStatusesByURI = new Object();
this.urlDetailByURI = new Object();
}
this.getRedirectTarget = function (uri)
{
var target = this.redirectTargetsByURI[uri];
return (target) ? target : uri;
}
this.setRedirectTarget = function (originalTarget, currentTarget)
{
this.redirectTargetsByURI[originalTarget] = currentTarget;
}
this.getCurrentTarget = function ()
{
return this.target;
}
this.setHttpResponseStatus = function (target, status)
{
var prev = parseInt(this.httpStatusesByURI[target]);
var cur = parseInt(status);
if ((! prev) || (prev > cur))
this.httpStatusesByURI[target] = status;
}
this.getHttpResponseStatus = function (target)
{
return (this.httpStatusesByURI[target]) ? this.httpStatusesByURI[target] : null;
}
this.start = function ()
{
this.disabled = false;
setTimeout(function (prefetcher) { prefetcher._start(); }, this.delayedStartInterval, this);
}
this.stop = function ()
{
this.disabled = true;
this._finishPrefetch("stop");
this.target = null;
this.URIsIndex = -1;
}
this.pause = function ()
{
this.disabled = true;
this._finishPrefetch("pause");
if ((this.URIsIndex >= this.URIsTopIndex) && (! this.allTargetsPrefetched))
{
this.URIsIndex--;
}
}
this.addEventListener = function (eventId, listener)
{
var listeners = this.eventListenerListsByEventId[eventId];
if (! listeners)
{
listeners = new Array();
this.eventListenerListsByEventId[eventId] = listeners;
}
else
{
this.removeEventListener(eventId, listener);
}
listeners.push(listener);
}
this.removeEventListener = function (eventId, listener)
{
var listeners = this.eventListenerListsByEventId[eventId];
var i;
for (i = 0; i < listeners.length; i++)
{
if (listener == listeners[i])
{
listeners = listeners.splice(i, 1);
break;
}
}
}
this.QueryInterface = function (iid)
{
if (!iid.equals(Components.interfaces.nsIWebProgressListener) &&
!iid.equals(Components.interfaces.nsISupportsWeakReference) && // not implemented
!iid.equals(Components.interfaces.nsISupports))
{
throw Components.errors.NS_ERROR_NO_INTERFACE;
}
return this;
}
this.onLocationChange = function (aWebProgress, aRequest, aLocation) {}
this.onProgressChange = function (aWebProgress, aRequest,
aCurSelfProgress, aMaxSelfProgress,
aCurTotalProgress, aMaxTotalProgress)
{
window.setCursor("auto");
setTimeout(function (window) { window.setCursor("auto"); }, 0, window);
}
this.onStateChange = function(aWebProgress, aRequest, aStateFlags, aStatus)
{
const nsIWPL = Components.interfaces.nsIWebProgressListener;
var originalUrl;
window.setCursor("auto");
setTimeout(function (window) { window.setCursor("auto"); }, 0, window);
if (! (aStateFlags & nsIWPL.STATE_IS_REQUEST))
return;
if (aStateFlags & nsIWPL.STATE_START)
{
// Kill alert and prompt on prefetch pages. -- JW
var win;
if (aWebProgress.DOMWindow.wrappedJSObject)
win = aWebProgress.DOMWindow.wrappedJSObject;
else
win = aWebProgress.DOMWindow;
win.alert = function (){};
win.prompt = function (){};
win.confirm = function (){};
win.open = function (){};
win.moveTo = function (){};
win.resizeTo = function (){};
win.sizeToContent = function (){};
this._dispatchEvent("progress-start");
}
try {
if (aWebProgress.DOMWindow != aWebProgress.DOMWindow.top)
return;
} catch (e) { return; } // ignore error accessing DOMWindow.top
if (aStateFlags & nsIWPL.STATE_STOP)
{
try {
var browser = document.getElementById(this.browserId);
var channel = browser.docShell.currentDocumentChannel;
var status = channel.responseStatus;
this.setHttpResponseStatus(this.target, status);
} catch (e) {}
// Notify the prefetcher that the document load is complete.
this.handleDocumentLoad("progress-stop");
}
}
this.onStatusChange = function (aWebProgress, aRequest, aStatus, aMessage)
{
window.setCursor("auto");
setTimeout(function (window) { window.setCursor("auto"); }, 0, window);
}
this.onSecurityChange = function (aWebProgress, aRequest, aState) {}
}
//### static attributes
su_Prefetcher.instanceCount = 0;